/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at

* http://www.apache.org/licenses/LICENSE-2.0

* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.

* File sample_process.h
* Description: handle acl resource
*/
#pragma once

#include <iostream>
#include <mutex>
#include <unistd.h>
#include <unordered_map>
#include <unordered_set>

#include "acl/acl.h"
#include "retina/object_detect.h"
#include "yolo/object_detection.h"
#include "deepsort/deep_sort.h"
#include "deepsort/SORT.h"
#include "dimp/dimp_tracker.h"
#include "target_storage.h"
#include "target_sender.h"
#include "utils.h"


class DoProcess{
public:
    DoProcess();
    ~DoProcess();

    enum class tasks {
        DeepSORT,
        SORT,
        Retina,
        DiMP
    };

    using processParams = struct {
        std::string input;          // 输入方式
        std::string task;            // 任务名
        std::vector<std::string> taskParams;  // 任务相关参数
        int listenPort;          // 网络接收监听端口
        std::string destination; // 输出位置
        std::string format;    // 输出形式
    };

    // only availible in this scope
    using ModelInfo = struct {
        std::string modelPath;
        int width;
        int height;
    };

    using ModelInfos = std::vector<ModelInfo>;
    // algorithm name -> model info list
    using ModelInfoMap = std::unordered_map<std::string, ModelInfos>;

    AtlasError Init(const processParams&);
    // Set在获取输入的视频或图像信息后调用，用于二次初始化业务对象。
    AtlasError InitStorage(uint32_t width, uint32_t height);
    AtlasError Process(ImageData& image);
private:
    

    AtlasError InitDeepSORT(ModelInfos&);
    AtlasError InitSORT(ModelInfos&);
    AtlasError InitDiMP(ModelInfos&);
    AtlasError InitRetina(ModelInfos&);

    AtlasError ProcessSORT(ImageData& image);
    AtlasError ProcessDeepSORT(ImageData& image);
    AtlasError ProcessDiMP(ImageData& image);
    AtlasError ProcessRetina(ImageData& image);

    AtlasError InitResource();
    void DestroyResource();
private:

    std::unordered_map<std::string, std::function<AtlasError(ModelInfos&)>> initMap_;
    std::unordered_map<std::string, std::function<AtlasError(ImageData&)>> processMap_;
    std::unordered_set<std::string> outputSet_;
    processParams params_;

    // 设备对象
    int32_t deviceId_;
    aclrtContext context_;
    aclrtStream stream_;
    aclrtRunMode runMode_;
    bool isInited_;

    // 业务对象
    std::shared_ptr<YoloObjectDetect> yolo_;
    std::shared_ptr<SORT> sort_;
    std::shared_ptr<DeepSort> deepsort_;
    std::shared_ptr<RetinaObjectDetect> retina_;
    std::shared_ptr<Tracker> dimp_;
    
    std::shared_ptr<TargetStorage> storage_;
    std::shared_ptr<TargetSender> sender_;

    std::once_flag onceFlag_;
};

